[小ネタ] S3に保存されているログファイルをAWS CLIでまとめてコピーする
はじめに
清水です。ELBやCloudFront、S3などのアクセスログはS3に保存されます。 アクセスログは外部ツールと連携させて監視や可視化するということもあると思いますが、直接ログファイルを確認することも多いのではないでしょうか。
ログファイルを直接確認するときはS3から作業用マシンにファイルをコピーしますが、保存先のS3バケット内のPrefixで指定したディレクトリにファイルが大量にあることが多いことから、私はAWS CLIを使ってコピーすることが多いです。
AWS CLIの場合、UNIXとまったく同じ書式でワイルドカードを使用することはできませんが、--recursiveオプションと--excludeオプション、--incluceオプションを組み合わせることで同様のことができます。
今回はアクセスログファイルから特定の日付のファイルだけを作業用マシン(AWS CLIを実行しているマシン)にコピーする、というシチュエーションでのコマンド例をまとめてみたいと思います。 (私がこの作業を行う際、都度コマンドオプション等を確認しているので個人的備忘録代わりにまとめてみました)
AWS CLI s3コマンドでの複数ファイル指定オプション
AWS CLIのs3コマンドでファイル指定の際に、例えば
aws s3 cp s3://bucket/logs/*.txt .
といったようなUNIXとまったく同じ書式でのワイルドカードは使用できません。
代わりに、--recursiveオプションを指定することで指定したディレクトリ配下のファイルをまるごと(再帰的に)コピーすることができます。
cp -r /path/to/directory/ .が aws s3 cp s3://bucket/path/to/directory/ . --recursive と同じイメージです。
さらに、指定した文字列を対象から外す--excludeオプションと、--excludeオプション対象から外した後に再度指定文字列を対象とする--includeオプション *1が用意されています。
これらのオプションに指定する文字列は以下のパターン記号が使用できます。
- *: Matches everything
- ?: Matches any single character
- [sequence]: Matches any character in sequence
- [!sequence]: Matches any character not in sequence
s3 - AWS CLI Command Reference 「Use of Exclude and Include Filters」
コピーするコマンド例
S3のログファイルのコピー
S3のログファイルのキーですが、以下の形式になります。
TargetPrefixYYYY-mm-DD-HH-MM-SS-UniqueString
AmazonS3 Developer Guide「サーバーアクセスのロギング - ログオブジェクトのキーフォーマット」
わかりやすいように、TargetPrefix=logs/s3/としますと以下のコマンドで指定の日付(ここでは2016/09/24)のログファイルがコピーできます。
aws s3 cp s3://bucket/ . --recursive --exclude "*" --include "logs/s3/2016-09-24*"
またはs3://からはじまるS3Uriの部分にTargetPrefixを指定してしまって以下のようにもできます。(私はこの書き方で行うことが多いです)
aws s3 cp s3://bucket/logs/s3/ . --recursive --exclude "*" --include "2016-09-24*"
ELBのログファイルコピー
ELBのログファイル *2のキーは以下のフォーマットです。
bucket[/prefix]/AWSLogs/aws-account-id/elasticloadbalancing/region/yyyy/mm/dd/aws-account-id_elasticloadbalancing_region_load-balancer-name_end-time_ip-address_random-string.log
Elastic Load Balancing Classic Load Balancers「標準ロードバランサーのアクセスログ - アクセスログファイル」
例えば、prefix=logs/elb、aws-account-id=123456789012、region=ap-northeast-1とした場合、以下のコマンドで特定の日付(ここでは2016/09/24)のログファイルがコピーできます。
aws s3 cp s3://bucket/logs/elb/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/2016/09/24/ . --recursive --exclude "*" --include "*.log"
または以下のようにすれば、アカウントIDの部分のもワイルドカードで指定することができます。
aws s3 cp s3://bucket/ . --recursive --exclude "*" --include "logs/elb/AWSLogs/*/elasticloadbalancing/ap-northeast-1/2016/09/24/*.log"
CloudFrontのログファイルのコピー
CloudFrontのログファイルのキーは以下になります。
bucket-name.s3.amazonaws.com/optional-prefix/distribution-ID.YYYY-MM-DD-HH.unique-ID.gz
Amazon CloudFront Developer Guide 「アクセスログ - ファイル名の形式」
optional-prefix=logs/cloudfrontとすると、以下のコマンドで特定の日付(ここでは2016/09/24)のログファイルがコピーできます。
aws s3 cp s3://bucket/logs/cloudfront/ . --recursive --exclude "*" --include "*2016-09-24*"
aws s3 cp s3://bucket/ . --recursive --exclude "*" --include "logs/cloudfront/*2016-09-24*.gz"
補足: 2つの書き方のどちらがよいか
2016/09/27、こちらの補足項目を追加しました。
S3、ELB、CloudFrontのログファイルをコピーするコマンド例として、 (1) S3Uriをなるべく深くとる方法、 (2) S3Uriを浅くとる(バケット名だけ)方法、 の2つを紹介しました。 特にELBについては、(2)だとアカウントIDを省略できる、という点もあるかな、とも思いましたが、以下の注意点があります。
AWS CLIのs3コマンドでは--excludeと--includeについての処理をコマンド実行マシン(ローカル)側で行っています。 そのため、(2)の方法を取った場合のほうが、--includeオプションの処理が多くなります。 ログファイルの件数が多い場合などはこの処理がとても長くなる可能性がありますので、S3Uriはなるべく深めに指定したほうがよいかと思います。
まとめ
S3には他にもいろいろなAWSログが出力されますが、基本はこのAWS CLIのs3 cpコマンドで作業マシンへのコピーができると思います。
UNIXとまったく同じ書式でのワイルドカード使用、とは行きませんが、--recursive、--exlucde、--includeについておさえることで、同じような感覚で使用できるのではないでしょうか。 またコピー対象が大量となる場合は--dryrunオプションで確認しながら行うとより確実かと思います。